﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using DTGroup.LTEPlanDesktop.WinUI.SuperMapForm;
using DTGroup.Networking.Framework;
using DTGroup.iNek.Model.FingerprintDatabase;
using System.IO;
using DTGroup.iNek.Configuration;
using System.Threading.Tasks;
using DTGroup.iNek.Business;
using DTGroup.iNek.Model;
using DTGroup.Networking.Framework.Utils;
using DTGroup.iNek.Utility;
using DTGroup.iNek.Business.FingerprintDatabase;
using Interface_Sample_DotNet;
using DTGroup.iNek.WinUI._Codes;
using DTGroup.iNek.Business.FingerprintDatabase.Provider;
using System.Runtime.InteropServices;

namespace DTGroup.iNek.WinUI.FingerPrintDatabase
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();

            IOCContainer.Register<ISuperMapProvider, SuperMapProviderImpl>();
        }
        private NLog.Logger logger = new NLog.LogFactory().GetCurrentClassLogger();

        private readonly WinpropCellResultBO winpropCellResultBO = new WinpropCellResultBO();

        MapBO mapBO = new MapBO();

        private void btnExcute_Click(object sender, EventArgs e)
        {
            if (EndFloot.Value < StartFloot.Value)
            {
                MessageBox.Show("请正确输入开始结束楼层");
                return;
            }

            // 水平偏移
            string FalseEasting = txtFalseEasting.Text;
            // 垂直偏移
            string FalseNorthing = txtFalseNorthing.Text;
            // CentralMeridian 中央经线角度值
            string CentralMeridian = txtCentralMeridian.Text;
            // 原点经纬度
            string CentralParallel = txtCentralParallel.Text;

            if (FalseEasting.IsNullOrEmpty() || FalseNorthing.IsNullOrEmpty() || CentralMeridian.IsNullOrEmpty() || CentralParallel.IsNullOrEmpty())
            {
                MessageBox.Show("请填写投影信息！");
                return;
            }

            int Error = 0;

            WinPropAPI.WinProp_Result NullResult = new WinPropAPI.WinProp_Result();
            Error = WinPropAPI.WinProp_Structure_Init_Result(ref NullResult);

            Dictionary<string, string> dataParameter = new Dictionary<string, string>();
            dataParameter.Add("FalseEasting", FalseEasting);
            dataParameter.Add("FalseNorthing", FalseNorthing);
            dataParameter.Add("CentralMeridian", CentralMeridian);
            dataParameter.Add("CentralParallel", CentralParallel);
            dataParameter.Add("ProjectionType", txtProjectType.Text);
            dataParameter.Add("GeoCoordSys", txtGeoCoordSys.Text);
            dataParameter.Add("SiteNewFilePath", txt_SiteNewAntFilePath.Text);
            dataParameter.Add("BuildVectorFilePath", txtBiuldVector.Text);
            dataParameter.Add("ODAOutPath", txtODAFilePath.Text);
            dataParameter.Add("WinpropPath", txtWinpropOutFilepath.Text);
            dataParameter.Add("GridLength", txtGridSteper.Text);
            dataParameter.Add("IsUserWinprop", "true");

            bool isTopo = checkBox1.Checked;
            string topoAddress = textBox1.Text;
            bool isClutter = checkBox2.Checked;
            string clutterAsc = textBox2.Text;
            string clutterTxt = textBox3.Text;

            dataParameter.Add("IsTopo", isTopo.ToString());
            dataParameter.Add("TopoAddress", topoAddress);
            dataParameter.Add("IsClutter", isClutter.ToString());
            dataParameter.Add("ClutterAsc", clutterAsc);
            dataParameter.Add("ClutterTxt", clutterTxt);

            dataParameter.Add("StartFloot", StartFloot.Value.ToString());
            dataParameter.Add("EndFloot", EndFloot.Value.ToString());

            if (this.backgroundWorker1.IsBusy == false)
            {
                this.backgroundWorker1.RunWorkerAsync(dataParameter);
                this.btnExcute.Enabled = false;
            }
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            this.backgroundWorker1.ReportProgress(1, "开始...");
            Dictionary<string, string> tempParameter = e.Argument as Dictionary<string, string>;
            FingerPrintDatabaseParameter dataParameter = new FingerPrintDatabaseParameter(tempParameter);

            // 设置 投影
            ProjectCoordSysType.OnInit(dataParameter);

            SiteNewBO.Instance.ReportProgressAction = (int progress, string message, Model.TaskStatus taskStatus) =>
            {
                this.backgroundWorker1.ReportProgress(progress, message);
            };

            if (dataParameter.SiteNewFilePath.Length > 0)
            {
                // 导入工参
                SiteNewBO.Instance.ImportSiteNew(dataParameter.SiteNewFilePath);
            }
            if (dataParameter.IsUserWinprop)
            {
                MapBO mapBO = new MapBO()
                {
                    ReportProgressAction = (int progress, string message, Model.TaskStatus taskStatus) =>
                    {
                        this.backgroundWorker1.ReportProgress(progress, message);
                    }
                };
                // 导入地图
                BiuldODAFile(dataParameter.BuildVectorFilePath, dataParameter.ODAOutPath);
                if (SiteSettings.Instance.DBType == 0)
                {
                    winpropCellResultBO.DeleteIndex();
                }

                // 射线追踪模型
                try
                {
                    this.CompPathLossByRayTracing(dataParameter.ODAOutPath, dataParameter.WinpropPath, dataParameter.GridLength, tempParameter);
                }
                catch(Exception ex)
                {
                    logger.Error(ex.Message);
                }
                
            }
        }

        public void BiuldODAFile(string buildVectorFilePath, string _ODAFilePath)
        {
            string _ODAFilePathResult = mapBO.GetMapODAFilePath(_ODAFilePath);
            // 如果该目录下已经存在建筑物数据，则不需要再次生成
            if (IOUtil.ExistsFile(_ODAFilePathResult) == false)
            {
                List<BuildingsObject> buildingsObjects = mapBO.ReadIndexFile(buildVectorFilePath);

                foreach (var item in buildingsObjects)
                {
                    using (SuperMap.Data.GeoPoint point = new SuperMap.Data.GeoPoint(Convert.ToDouble(item.MinX), Convert.ToDouble(item.MinY)))
                    {
                        CoordSysTranslatorHandler.Instance.ConvertCoordSys(point, ProjectCoordSysType.MapPrjCoordSys, ProjectCoordSysType.LatLonPrjCoordSys);
                        CoordSysTranslatorHandler.Instance.ConvertCoordSys(point, ProjectCoordSysType.LatLonPrjCoordSys, ProjectCoordSysType.MercatorPrjCoordSys);
                        item.MinX = point.X;
                        item.MinY = point.Y;
                    }

                    using (SuperMap.Data.GeoPoint point = new SuperMap.Data.GeoPoint(Convert.ToDouble(item.MaxX), Convert.ToDouble(item.MaxY)))
                    {
                        CoordSysTranslatorHandler.Instance.ConvertCoordSys(point, ProjectCoordSysType.MapPrjCoordSys, ProjectCoordSysType.LatLonPrjCoordSys);
                        CoordSysTranslatorHandler.Instance.ConvertCoordSys(point, ProjectCoordSysType.LatLonPrjCoordSys, ProjectCoordSysType.MercatorPrjCoordSys);
                        item.MaxX = point.X;
                        item.MaxY = point.Y;
                    }
                }

                if (buildingsObjects != null)
                {
                    BuildingsObject buildingsObject = new BuildingsObject()
                    {
                        MinX = buildingsObjects.Min(o => o.MinX),
                        MaxX = buildingsObjects.Max(o => o.MaxX),
                        MinY = buildingsObjects.Min(o => o.MinY),
                        MaxY = buildingsObjects.Max(o => o.MaxY)
                    };

                    Dictionary<int, BuildingVectorObject> buildingsVectorDic = new Dictionary<int, BuildingVectorObject>();
                    int orderOID = 1;
                    // 遍历 所有的Buildings 文件
                    foreach (BuildingsObject item in buildingsObjects)
                    {
                        orderOID = ReadBuildingsFileContent(buildingsVectorDic, item, orderOID, buildingsObject);
                    }

                    // 输出ODA文件
                    mapBO.OutODAFilePath(buildingsVectorDic, mapBO.GetMapODAFilePath(_ODAFilePath), buildingsObject);
                    buildingsVectorDic.Clear();
                    buildingsVectorDic = null;
                }
            }
        }

        /// <summary>
        /// 设置 进度
        /// </summary>
        /// <param name="value"></param>
        /// <param name="message"></param>
        private void SetProgressValue(int value, string message)
        {
            this.lblMessage.Text = string.Format("{0}[{1}%]", message, value);
            this.progressBar1.Value = value;
        }

        /// <summary>
        /// 调用射线跟踪模块计算规划区域内所有小区各自覆盖区域内的路径损耗
        /// </summary>
        private int CompPathLossByRayTracing(string odaOutPath, string winpropFilePath, int gridlength, Dictionary<string, string> tempParameter)
        {
            #region 这两个参数是调试过程，临时设置的参数，都设置成FALSE
            bool bTopoSwitch = Convert.ToBoolean(tempParameter["IsTopo"]);
            bool bClutterSwitch = Convert.ToBoolean(tempParameter["IsClutter"]);
            #endregion

            //立体指纹库，开始楼层
            int startFloot = Convert.ToInt32(tempParameter["StartFloot"]);
            //立体指纹库，结束楼层
            int endFloot = Convert.ToInt32(tempParameter["EndFloot"]);
            //winprop内置类
            WinPropAPI.WinProp_ParaMain tempGeneralParameters = new WinPropAPI.WinProp_ParaMain();
            //winprop加载地图文件，ODA文件
            WinPropAPI.InterfaceLoadBuildingsASCII(ref tempGeneralParameters.Buildings, odaOutPath + "\\BuildingVector.ODA");

            #region 代码可注释，调试使用
            if (bTopoSwitch == true)
            {
                WinPropAPI.InterfaceLoadTopoASC(ref tempGeneralParameters.Topography, tempParameter["TopoAddress"]);
            }

            if (bClutterSwitch == true)
            {
                WinPropAPI.InterfaceLoadClutterASC(ref tempGeneralParameters.Clutter, tempParameter["ClutterAsc"], tempParameter["ClutterTxt"]);
            }
            #endregion

            int Error = 0;
            //小区列表
            List<Cell> cells = CellBO.Instance.GetAll().ToList();
            //天线列表
            CellAntParameterCollection cellantParameters = CellAntParameterBO.Instance.CellAntParameters;

            #region 遍历小区，转换小区经纬度位魔卡托
            foreach (var item in cells)
            {
                using (SuperMap.Data.GeoPoint point = new SuperMap.Data.GeoPoint(item.CellLongitude, item.CellLatitude))
                {
                    CoordSysTranslatorHandler.Instance.ConvertCoordSys(point, ProjectCoordSysType.LatLonPrjCoordSys, ProjectCoordSysType.MercatorPrjCoordSys);
                    item.CellLongitude = point.X;
                    item.CellLatitude = point.Y;
                };
            }
            #endregion


            //统计需要参与射线跟踪计算的小区个数，用于记录进度
            int baseOnwinpropCellNum = cells.Count;
            logger.Info(string.Format("小区个数为：{0}", baseOnwinpropCellNum));
            // 记录进度 

            /*分配多线程*/
            int parallelThreadCount = ConfigurationManger.Instance.FingerprintDatabase_SettingsExt.WinpropThreadCount;
            int threadContentCount = cells.Count() / parallelThreadCount;
            if (threadContentCount == 0)
            {
                threadContentCount = baseOnwinpropCellNum;
            }

            if (cells.Count % parallelThreadCount > 0)
            {
                threadContentCount++;
            }

            List<WinpropParallelThreadParameter> parallelThreadList = new List<WinpropParallelThreadParameter>();
            for (int i = 0; i < parallelThreadCount; i++)
            {
                WinpropParallelThreadParameter winpropParameter = new WinpropParallelThreadParameter()
                {
                    CellListTemp = cells.Skip(i * threadContentCount).Take(threadContentCount).ToList()
                };
                parallelThreadList.Add(winpropParameter);
            }

            logger.Info("开始执行射线追踪模型计算。。。");

            Dictionary<int, double> dicPropagationEnviron = new Dictionary<int, double>();
            dicPropagationEnviron = PropagationEnvironBO.Instance.GetAllDictionaryPredictDistance();

            Dictionary<int, ResourceConfig> dicResourceConfig = new Dictionary<int, ResourceConfig>();
            dicResourceConfig = ResourceConfigBO.Instance.GetDicResourceConfig();

            for (int i = startFloot; i <= endFloot; i++)
            {
                this.backgroundWorker1.ReportProgress(0, "射线跟踪模型路损计算");
                int tempCellNum = 0;
                int prevProgressValue = 0;

                Parallel.ForEach(parallelThreadList, new ParallelOptions() { MaxDegreeOfParallelism = parallelThreadCount }, (WinpropParallelThreadParameter winpropParameter) =>
                {
                    foreach (var cell in winpropParameter.CellListTemp)
                    {
                        try
                        {
                            //当前小区射线跟踪计算输出文件存储路径及读取开关设置                                                            
                            string winpropRecordPath = IOUtil.JoinPath(winpropFilePath, gridlength.ToString());
                            string winpropOutFileNam = CellBO.Instance.GetCellWinPropFilePath(i + "\\" + cell.CellName, gridlength, winpropFilePath);

                            if (IOUtil.ExistsFile(winpropOutFileNam) == false)
                            {
                                if (!IOUtil.ExistsDirectory(winpropRecordPath))
                                {
                                    IOUtil.CreateDirectory(winpropRecordPath);
                                }

                                if (!IOUtil.ExistsDirectory(winpropRecordPath + "\\" + i))
                                {
                                    IOUtil.CreateDirectory(winpropRecordPath + "\\" + i);
                                }
                            }
                            else
                            {
                                continue;
                            }

                            winpropRecordPath = winpropRecordPath + "\\" + i;

                            WinPropAPI.WinProp_ParaMain GeneralParameters = new WinPropAPI.WinProp_ParaMain();

                            WinPropAPI.WinProp_Structure_Init_ParameterMain(ref GeneralParameters);

                            GeneralParameters.Buildings = tempGeneralParameters.Buildings;

                            if (bTopoSwitch == true)
                            {
                                /* Topo pixel data in ASCII grid *.asc format read into RAM */
                                GeneralParameters.TopographyMode = 1;
                                GeneralParameters.Topography = tempGeneralParameters.Topography;
                            }

                            if (bClutterSwitch == true)
                            {
                                ///* Clutter pixel data in ASCII grid *.asc format and clutter properties read into RAM */
                                GeneralParameters.ClutterMode = 0;
                                GeneralParameters.Clutter = tempGeneralParameters.Clutter;
                            }

                            GeneralParameters.ScenarioMode = 1; // Urban prediction
                            //射线优势主路径
                            GeneralParameters.PredictionModelUrban = 1; // Use Dominant Path Model

                            GeneralParameters.SupressMessageBoxes = 1;

                            double predictDistance = dicPropagationEnviron[cell.PropagationEnvironOID];

                            GeneralParameters.UrbanLowerLeftX = cell.CellLongitude - predictDistance;
                            GeneralParameters.UrbanLowerLeftY = cell.CellLatitude - predictDistance;
                            GeneralParameters.UrbanUpperRightX = cell.CellLongitude + predictDistance;
                            GeneralParameters.UrbanUpperRightY = cell.CellLatitude + predictDistance;

                            /* Copy coordinates to prediction area of second model (not yet used) */
                            GeneralParameters.RuralLowerLeftX = GeneralParameters.UrbanLowerLeftX;
                            GeneralParameters.RuralLowerLeftY = GeneralParameters.UrbanLowerLeftY;
                            GeneralParameters.RuralUpperRightX = GeneralParameters.UrbanUpperRightX;
                            GeneralParameters.RuralUpperRightY = GeneralParameters.UrbanUpperRightY;

                            /* Size of matrix with results. */
                            //栅格步长
                            GeneralParameters.Resolution = gridlength; // Resolution in meter

                            GeneralParameters.MatrixFormat = 0;

                            GeneralParameters.MatrixWidth = (uint)((GeneralParameters.UrbanUpperRightX - GeneralParameters.UrbanLowerLeftX) / GeneralParameters.Resolution + 1.0);
                            GeneralParameters.MatrixHeight = (uint)((GeneralParameters.UrbanUpperRightY - GeneralParameters.UrbanLowerLeftY) / GeneralParameters.Resolution + 1.0);

                            //楼层高度
                            if (i == 0)
                            {
                                GeneralParameters.PredictionHeight = i * ConfigurationManger.Instance.FingerprintDatabase_SettingsExt.FloorHeight + 1.5; // Prediction height in meter
                            }
                            else
                            {
                                GeneralParameters.PredictionHeight = i * ConfigurationManger.Instance.FingerprintDatabase_SettingsExt.FloorHeight;
                            }

                            GeneralParameters.BuildingsMode = 1;

                            //WinPropAPI.InterfaceLoadBuildingsASCII(ref GeneralParameters.Buildings, winpropParameter.ODAFilePath);                                

                            //GeneralParameters.BuildingsIndoorCoverage = 1;

                            //GeneralParameters.BuildingsIndoorDecrease = 0.4;

                            GeneralParameters.BuildingsIndoorCoverage = 3;  //We suggest to use the model 3
                            GeneralParameters.BuildingsIndoorDecrease = 0.6;

                            WinPropAPI.WinProp_Antenna DataAntenna = new WinPropAPI.WinProp_Antenna();
                            Error = WinPropAPI.WinProp_Structure_Init_Antenna(ref DataAntenna);

                            #region
                            WinPropAPI.WinProp_Pattern AntennaPattern = new WinPropAPI.WinProp_Pattern();
                            Error = WinPropAPI.WinProp_Structure_Init_Pattern(ref AntennaPattern);

                            AntennaPattern.Mode = 2;
                            AntennaPattern.Filename = @"C:\router_directional.apb"; //定向天线

                            #endregion

                            ResourceConfig currentResourceConfig = dicResourceConfig[cell.ResourceConfigOID];

                            float frequency = (currentResourceConfig.StartFrequence + currentResourceConfig.EndFrequence) / 2.0f;

                            DataAntenna.Longitude_X = cell.CellLongitude;
                            DataAntenna.Latitude_Y = cell.CellLatitude;
                            DataAntenna.Height = cellantParameters.FirstOrDefault(o => o.CellOID == cell.OID).AntHeight; ;
                            DataAntenna.Power = cell.RSTxPower; //工参文件中一般设为15.2//PublicToolsKernel.DB(PublicToolsKernel.DB_Inverse(cell.RSTxPower) * 12 * 100); ; // Power in dBm
                            DataAntenna.Frequency = frequency;
                            DataAntenna.Name = cell.CellName;
                            DataAntenna.Azimuth = cellantParameters.FirstOrDefault(o => o.CellOID == cell.OID).HorizonAngleToEast;
                            DataAntenna.Downtilt = cellantParameters.FirstOrDefault(o => o.CellOID == cell.OID).VerticalAngleToHorizontal;

                            DataAntenna.Pattern = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(WinPropAPI.WinProp_Pattern)));

                            Marshal.StructureToPtr(AntennaPattern, DataAntenna.Pattern, false);

                            /* Fill "WinProp_Callback" for definition of callback functions. */
                            WinPropAPI.WinProp_Callback DataCallback = new WinPropAPI.WinProp_Callback();
                            WinPropAPI.ProgressCallBackPtr ProgressPointer = new WinPropAPI.ProgressCallBackPtr(OnCallbackProgress);
                            WinPropAPI.MessageCallBackPtr MessagePointer = new WinPropAPI.MessageCallBackPtr(OnCallbackMessages);
                            DataCallback.Percentage = ProgressPointer;
                            DataCallback.Message = MessagePointer;

                            WinPropAPI.WinProp_Result PropResult = new WinPropAPI.WinProp_Result();

                            /* Compute prediction with the function "WinProp_Predict()". */
                            //Error = WinPropAPI.OutdoorPlugIn_ComputePrediction(ref DataAntenna, ref GeneralParameters, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref DataCallback, ref PropResult, IntPtr.Zero, IntPtr.Zero);
                            //Error = WinPropAPI.OutdoorPlugIn_ComputePrediction(ref DataAntenna, ref GeneralParameters, ref ParametersDPM, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref DataCallback, ref PropResult, IntPtr.Zero, IntPtr.Zero);

                            GeneralParameters.AdditionalResultMode = 2;
                            GeneralParameters.AdditionalResult = @"G:\桌面\output";

                            WinPropAPI.WinProp_Model_DPM ParametersDPM = new WinPropAPI.WinProp_Model_DPM();
                            Error = WinPropAPI.WinProp_Structure_Init_Model_DPM(ref ParametersDPM);
                            ParametersDPM.DiffrLoss = 13.0;
                            ParametersDPM.ExponentLOS = 2.5;
                            ParametersDPM.ExponentLOSafterBP = 4.0;
                            ParametersDPM.ExponentOLOS = 2.8;
                            ParametersDPM.ExponentOLOSafterBP = 4.0;
                            ParametersDPM.AdaptiveResolution = 0;
                            ParametersDPM.Waveguiding = 0;
                            ParametersDPM.BuildingLossPerMeter = 0.015;
                            GeneralParameters.BreakpointFactor = 12.56;
                            GeneralParameters.BuildingsMaterialsInd = 0;
                            GeneralParameters.BuildingsTransmissionLoss = 20.0;
                            GeneralParameters.Filter = 0;
                            GeneralParameters.UseAntennaLimit = 0;

                            Error = WinPropAPI.OutdoorPlugIn_ComputePrediction(ref DataAntenna, ref GeneralParameters, ref ParametersDPM, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, ref DataCallback, ref PropResult, IntPtr.Zero, IntPtr.Zero);

                            if (Error != 0)
                                return;

                            Marshal.FreeHGlobal(DataAntenna.Pattern); //释放DataAntenna所分配的内存空间

                            /* Allow access to result matrix and safe this to an ASCII file. */
                            unsafe
                            {
                                /* Create triple pointer to double values of result. */
                                float*** ResultMatrix = (float***)PropResult.Matrix.ToPointer();

                                /* Create file for output. */
                                //FileStream fs = new FileStream("PredictionResult.txt", FileMode.Create);
                                FileStream fs = new FileStream(winpropOutFileNam, FileMode.Create);
                                StreamWriter writer = new StreamWriter(fs);

                                /* Consider height 0 only. */
                                int h = 0;

                                /* Loop all columns. */
                                for (int x = 0; x < PropResult.Columns; x++)
                                {
                                    /* Compute x real. */
                                    double x_real = PropResult.LowerLeftX + ((double)x + 0.5) * PropResult.Resolution;

                                    /* Loop all lines. */
                                    for (int y = 0; y < PropResult.Lines; y++)
                                    {
                                        /* Compute y real. */
                                        double y_real = PropResult.LowerLeftY + ((double)y + 0.5) * PropResult.Resolution;

                                        /* Write value. */
                                        float Value = ResultMatrix[h][x][y];

                                        if (bClutterSwitch == true)
                                        {
                                            /* Consider clutter data and determine clutterID for this pixel first */
                                            int** ClutterMatrix = (int**)GeneralParameters.Clutter.clutterData.ToPointer();
                                            int clutter_x = Convert.ToInt32(Math.Floor((x_real - GeneralParameters.Clutter.lowerLeftX) / (GeneralParameters.Clutter.resolutionX)));
                                            int clutter_y = Convert.ToInt32(Math.Floor((y_real - GeneralParameters.Clutter.lowerLeftY) / (GeneralParameters.Clutter.resolutionY)));

                                            int ClutterClassIndex = 0;
                                            if (clutter_x >= 0 && clutter_y >= 0 && clutter_x < GeneralParameters.Clutter.columns && clutter_y < GeneralParameters.Clutter.rows)
                                                ClutterClassIndex = ClutterMatrix[clutter_x][clutter_y] - 1;

                                            /* Determine clutter loss or attenuation based on clutterID */
                                            var structSize = Marshal.SizeOf(typeof(WinPropAPI.WinProp_CLUTTER_CLASS));
                                            var ClutterClassPtr = new IntPtr(GeneralParameters.Clutter.classes.ToInt64() + structSize * ClutterClassIndex);
                                            var ClutterClass = (WinPropAPI.WinProp_CLUTTER_CLASS)Marshal.PtrToStructure(ClutterClassPtr, typeof(WinPropAPI.WinProp_CLUTTER_CLASS));

                                            double ClutterLoss = 0.0;
                                            var ClutterAttenuation = (WinPropAPI.WinProp_FREQUENCY_LOSS)Marshal.PtrToStructure(ClutterClass.Attenuation, typeof(WinPropAPI.WinProp_FREQUENCY_LOSS));
                                            ClutterLoss = Convert.ToDouble(ClutterAttenuation.Loss_dB); /* Assuming there is only one frequency band i.e. array Attenuation has just one element */

                                            /* Subtract positive clutter loss from negative pathloss in dB */
                                            Value = Value - Convert.ToSingle(ClutterLoss);
                                        }

                                        //// 电场强度 E[dBuV/m] = 77.21 + 20*log10(f/MHz) + RxPower[dBm]
                                        //double ValueE = 77.21 + 20 * (Math.Log10(DataAntenna.Frequency)) + Value + DataAntenna.Power;
                                        // Export the RxPower
                                        double RxPowerValue = Value + DataAntenna.Power;

                                        /* Write value. */
                                        writer.WriteLine(String.Format(System.Globalization.NumberFormatInfo.InvariantInfo, "{0:F}\t{1:F}\t{2:F}", x_real, y_real, RxPowerValue));
                                        //writer.WriteLine(String.Format(System.Globalization.NumberFormatInfo.InvariantInfo, "{0:F}", RxPowerValue));
                                    }
                                }

                                /* Close everything. */
                                writer.Close();
                                fs.Close();
                            }
                            /* Free matrix for results */
                            WinPropAPI.WinProp_FreeResult(ref PropResult);
                            ///* Free matrix for buildings */
                            //WinPropAPI.InterfaceBuildingsFree(ref (GeneralParameters.Buildings));


                            // 记录进度
                            int fProcess = Convert.ToInt32((float)tempCellNum * 100 / baseOnwinpropCellNum);
                            if (fProcess > prevProgressValue)
                            {
                                if (fProcess > 100) { fProcess = 100; }
                                this.backgroundWorker1.ReportProgress(fProcess, "射线追踪模型路损计算...");
                                prevProgressValue = fProcess;
                            }

                            tempCellNum++;
                        }
                        catch (Exception ex)
                        {
                            if (ex.InnerException != null)
                            {
                                logger.Error("射线追踪异常：" + ex.InnerException.Message + ex.InnerException.StackTrace);
                                logger.Error("CellName：" + cell.CellName);
                            }
                            logger.Error(ex.Source + "," + ex.Message + "," + ex.StackTrace);
                        }
                    }
                });
            }

            /* Free matrix for buildings */
            WinPropAPI.InterfaceBuildingsFree(ref (tempGeneralParameters.Buildings));
            if (bTopoSwitch == true)
            {
                /* Free matrix for topography */
                WinPropAPI.InterfaceTopoFree(ref (tempGeneralParameters.Topography));
            }
            if (bClutterSwitch == true)
            {
                /* Free matrix for clutter */
                WinPropAPI.InterfaceClutterFree(ref (tempGeneralParameters.Clutter));
            }

            logger.Info("执行射线追踪模型计算结束。。。");

            this.backgroundWorker1.ReportProgress(100, "射线跟踪模型路损计算");

            return (Error);
        }

        public void loc_to_mercator(double lon, double lat, ref double miX, ref double minY)
        {
            double x = lon;
            double y = Math.Log(Math.Tan((lat / 180 * Math.PI + Math.PI / 2) / 2)) * 180 / Math.PI;
            miX = x * 20037508.3427892 / 180;
            minY = y * 20037508.3427892 / 180;
        }

        public void mercator_to_loc(double mercator_x, double mercator_y, ref double lon, ref double lat)
        {
            double x = mercator_x / 20037508.3427892 * 180;
            double y = mercator_y / 20037508.3427892 * 180;
            lon = x;
            lat = 180 / Math.PI * (2 * Math.Atan(Math.Exp(y * Math.PI / 180)) - Math.PI / 2);
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e != null)
            {
                if (e.UserState != null)
                {
                    if (e.ProgressPercentage > 100)
                    {
                        SetProgressValue(100, e.UserState.ToString());
                    }
                    else
                    {
                        SetProgressValue(e.ProgressPercentage, e.UserState.ToString());
                    }
                }
            }
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.btnExcute.Enabled = true;
            if (e.Error == null)
            {
                MessageBox.Show("指纹库执行完成！");
            }
            else
            {
                this.logger.Error("异常信息如下：{0}，{1}", e.Error.Message, e.Error.StackTrace);
                MessageBox.Show("操作异常：" + e.Error.Message);
            }
        }

        private void btn_ODAFilePath_Click(object sender, EventArgs e)
        {
            using (FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog())
            {
                folderBrowserDialog.Description = "请选择“ODA输出文件”路径";

                if (DialogResult.OK == folderBrowserDialog.ShowDialog())
                {
                    txtODAFilePath.Text = folderBrowserDialog.SelectedPath;
                }
            }
        }

        private void btnWinprop_Click(object sender, EventArgs e)
        {
            using (FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog())
            {
                folderBrowserDialog.Description = "请选择“Winprop输出文件”路径";

                if (DialogResult.OK == folderBrowserDialog.ShowDialog())
                {
                    txtWinpropOutFilepath.Text = folderBrowserDialog.SelectedPath;
                }
            }
        }

        private void btnBuildVector_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "";
                openFileDialog.AutoUpgradeEnabled = false;

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string fileName = openFileDialog.FileName;
                    if (IOUtil.ExistsFile(fileName))
                    {
                        txtBiuldVector.Text = fileName;
                    }
                }
            }
        }

        private void buttonSiteNew_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "(*.xlsx;*.xls)|*.xlsx;*.xls";
                openFileDialog.AutoUpgradeEnabled = false;

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string fileName = openFileDialog.FileName;
                    if (IOUtil.ExistsFile(fileName))
                    {
                        txt_SiteNewAntFilePath.Text = fileName;
                    }
                }
            }
        }

        private void btnGeoCoordSys_Click(object sender, EventArgs e)
        {
            GeoCoordSysForm geocoordSysForm = new GeoCoordSysForm();
            geocoordSysForm.ShowDialog();

            if (string.IsNullOrEmpty(geocoordSysForm.GeoCoordSysName) == false)
            {
                txtGeoCoordSys.Text = geocoordSysForm.GeoCoordSysName;
            }
        }

        private void btnProjectionType_Click(object sender, EventArgs e)
        {
            ProjectionForm projectionForm = new ProjectionForm();
            projectionForm.ShowDialog();

            if (projectionForm.ProjectionName.IsNullOrEmpty() == false)
            {
                txtProjectType.Text = projectionForm.ProjectionName;
            }
        }

        public int ReadBuildingsFileContent(Dictionary<int, BuildingVectorObject> buildingVectorObjects, BuildingsObject buildingsObject, int orderOID, BuildingsObject totalBuildingsObject)
        {
            BuildingVectorObject buildVectorObject = null;
            int prevProgressValue = 0;
            int rowCount = 0;
            // 读取 文件的行数
            FileUtil.ReadFileLineContent(buildingsObject.BuildingsFilePath, delegate(string readerLineContent)
            {
                if (string.IsNullOrEmpty(readerLineContent) == false)
                {
                    rowCount++;
                }
            });

            int cusor = 1;
            int tempOrderOID = orderOID;
            // 读取 Index 文件内容
            FileUtil.ReadFileLineContent(buildingsObject.BuildingsFilePath, delegate(string readerLineContent)
            {
                if (string.IsNullOrEmpty(readerLineContent) == false)
                {
                    string[] readerLineArray = IteratorUtil.Trim(readerLineContent.Split(new char[] { ' ' }));

                    if (readerLineArray.Length == 3)
                    {
                        if (cusor > 1)
                        {
                            buildingVectorObjects.Add(buildVectorObject.OID, buildVectorObject);
                        }

                        buildVectorObject = new BuildingVectorObject()
                        {
                            OID = tempOrderOID,
                            Index = Convert.ToInt32(readerLineArray[0]),
                            VectorPointCount = Convert.ToInt32(readerLineArray[2])
                        };

                        tempOrderOID++;
                    }
                    else if (readerLineArray.Length == 2)
                    {
                        double longitude = double.Parse(readerLineArray[0]);
                        double latitude = double.Parse(readerLineArray[1]);

                        using (SuperMap.Data.GeoPoint point = new SuperMap.Data.GeoPoint(longitude, latitude))
                        {
                            CoordSysTranslatorHandler.Instance.ConvertCoordSys(point, ProjectCoordSysType.MapPrjCoordSys, ProjectCoordSysType.LatLonPrjCoordSys);
                            CoordSysTranslatorHandler.Instance.ConvertCoordSys(point, ProjectCoordSysType.LatLonPrjCoordSys, ProjectCoordSysType.MercatorPrjCoordSys);

                            longitude = point.X;
                            latitude = point.Y;
                        }

                        buildVectorObject.VectorPoints.Add(new VectorPoint()
                        {
                            longitude = longitude,
                            Latitude = latitude,
                            Relativelongitude = double.Parse((longitude - totalBuildingsObject.MinX).ToString("0.0000")),
                            RelativeLatitude = double.Parse((latitude - totalBuildingsObject.MinY).ToString("0.0000"))
                        });
                    }

                    int currentProgressValue = Convert.ToInt32(cusor * 100 / rowCount);
                    if (currentProgressValue > prevProgressValue)
                    {
                        prevProgressValue = currentProgressValue;
                        this.backgroundWorker1.ReportProgress(currentProgressValue, string.Format("正在读取{0}文件...", DTGroup.Networking.Framework.Utils.IOUtil.GetFileName(buildingsObject.BuildingsFilePath)));
                    }

                    cusor++;
                }
            });

            if (buildingVectorObjects.Count > 0)
            {
                mapBO.ReadBuildingsAttribute(buildingVectorObjects, buildingsObject, orderOID);
            }

            return tempOrderOID;
        }

        private int OnCallbackProgress(int progress, string text)
        {
            /* TODO: Print progress (0 to 100%) to screen.. */
            return (0);
        }

        private int OnCallbackMessages(string text)
        {
            /* TODO: Print current message to screen.. */
            return (0);
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            textBox1.Enabled = checkBox1.Checked;
            button1.Enabled = checkBox1.Checked;
        }

        private void checkBox2_CheckedChanged(object sender, EventArgs e)
        {
            textBox2.Enabled = checkBox2.Checked;
            textBox3.Enabled = checkBox2.Checked;
            button2.Enabled = checkBox2.Checked;
            button3.Enabled = checkBox2.Checked;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "";
                openFileDialog.AutoUpgradeEnabled = false;

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string fileName = openFileDialog.FileName;
                    if (IOUtil.ExistsFile(fileName))
                    {
                        textBox1.Text = fileName;
                    }
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "";
                openFileDialog.AutoUpgradeEnabled = false;

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string fileName = openFileDialog.FileName;
                    if (IOUtil.ExistsFile(fileName))
                    {
                        textBox2.Text = fileName;
                    }
                }
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "";
                openFileDialog.AutoUpgradeEnabled = false;

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string fileName = openFileDialog.FileName;
                    if (IOUtil.ExistsFile(fileName))
                    {
                        textBox3.Text = fileName;
                    }
                }
            }
        }
    }
}